//使用JavaScript实现观察者模式，即模仿浏览器的事件监听机制的实现
//其实这就是Ext.util.Obserable的核心设计思路
(function() {
	//被观察者类
	var Obserable = function() {
		//预置事件
		this.events = ["start", "stop"];
		/**
		 * 类似于map，存放事件-回调函数， value是一个数组
		 */
		this.listeners = {};
	};
	
	//添加事件
	Obserable.prototype.addEvent = function(event) {
		if (!event || typeof event !== "string") {
			throw {
				message: "参数非法!"
			};
		}
		if (this.events.indexOf(event) === -1) {
			this.events.push(event);
		}
	}
	
	/**
	 * 添加监听器
	 * @param event 需要监听的事件名称
	 * @param fn 回调函数
	 */
	Obserable.prototype.addListener = function(event, fn) {
		if (!event || !fn || typeof event !== "string" || typeof fn !== "function") {
			throw {
				message: "参数非法!"
			};
		}
		var array = this.listeners[event];
		if (!array) {
			array = this.listeners[event] = [fn];
		} else if (array.indexOf(fn) === -1) {
			array.push(fn);
		}
	}
	
	/**
	 * 移除监听器
	 * @param event 事件名称
	 * @param fn 需要移除的函数
	 */
	Obserable.prototype.removeListener = function(event, fn) {
		if (!event || !fn || typeof event !== "string" || typeof fn !== "function") {
			throw {
				message: "参数非法!"
			};
		}
		var array = this.listeners[event],
					pos;
		if (array && (pos = array.indexOf(fn)) !== -1) {
			array.splice(pos, 1);
		}
	}
	
	/**
	 * 触发监听器
	 * @param event 事件名称
	 */
	Obserable.prototype.fireEvent = function(event) {
		if (!event || typeof event !== "string") {
			throw {
				message: "参数非法!"
			};
		}
		var array = this.listeners[event];
		if (array) {
			for (var i = 0, l = array.length; i < l;i ++) {
				array[i].call(this);
			}
		}
	}
	
	//提供简写
	Obserable.prototype.on = Obserable.prototype.addListener;
	Obserable.prototype.un = Obserable.prototype.removeListener;
	
	//测试
	var obserable = new Obserable();
	obserable.on("start", function() {
		alert("start事件触发");
	});
	obserable.on("stop", function() {
		alert("stop事件触发");
	});
	obserable.fireEvent("start");
	obserable.fireEvent("stop");
	obserable.on("click", function() {
		alert("click事件触发");
	});
	obserable.fireEvent("click");
})();